package org.wangp.gateway.sc.config

import cn.hutool.core.util.ArrayUtil
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.convert.converter.Converter
import org.springframework.security.authentication.AbstractAuthenticationToken
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.config.web.server.ServerHttpSecurity
import org.springframework.security.oauth2.jwt.Jwt
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter
import org.springframework.security.web.server.SecurityWebFilterChain
import org.wangp.gateway.sc.constant.AuthConstant
import reactor.core.publisher.Mono


/**
 * @author wangpeng (๑•ᴗ•๑)
 * @since 2021/10/6 17:17
 */
@Configuration
@EnableWebFluxSecurity
class ResourceServerConfig(
	private val authorizationManager: AuthorizationManager,
	private val restfulAccessDeniedHandler: RestfulAccessDeniedHandler,
	private val restAuthenticationEntryPoint: RestAuthenticationEntryPoint
) {


	@Bean
	fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain? {
		http.oauth2ResourceServer().jwt()
			.jwtAuthenticationConverter(jwtAuthenticationConverter())
		http.authorizeExchange()
			.pathMatchers("/actuator/**", "/auth/oauth/token").permitAll() //白名单配置
			.anyExchange().access(authorizationManager) //鉴权管理器配置
			.and().exceptionHandling()
			.accessDeniedHandler(restfulAccessDeniedHandler) //处理未授权
			.authenticationEntryPoint(restAuthenticationEntryPoint) //处理未认证
			.and().csrf().disable()
		return http.build()
	}


	@Bean
	fun jwtAuthenticationConverter(): Converter<Jwt?, out Mono<out AbstractAuthenticationToken?>?>? {
		val jwtGrantedAuthoritiesConverter = JwtGrantedAuthoritiesConverter()
		jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX)
		jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME)
		val jwtAuthenticationConverter = JwtAuthenticationConverter()
		jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter)
		return ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter)
	}
}
